package com.example.recorder;

import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * Created by hdz on 2017/12/23.
 */

public class Logger {

    private static final String TAG = "Demo";
    private static boolean bOutLog = true;
    private static boolean bSaveLog = true;

    public static void d(String tag, String log) {
        log(Log.DEBUG, tag, log);
    }
    public static void d(String tag, int log) {
        d(tag, "" + log);
    }
    public static void d(String tag, String log, boolean out) {if (out)d(tag, log);}
    public static void d(String tag, int    log, boolean out) {if (out)d(tag, log);}
    public static void d(String log, boolean out) {if (out) d(log);}
    public static void d(int    log, boolean out) {if (out)d(log);}
    public static void d(String log) {d(TAG, log);}
    public static void d(int log) {d(TAG, ""+log);}


    public static void e(String tag, String log) {
        log(Log.ERROR, tag, log);
    }
    public static void e(String tag, int log) {e(tag, "" + log);}
    public static void e(String tag, String log, boolean out){if (out)e(tag, log);}
    public static void e(String tag, int    log, boolean out){if (out)e(tag, log);}
    public static void e(String log, boolean out){if (out) e(log);}
    public static void e(int    log, boolean out){if (out) e(log);}
    public static void e(String log) {e(TAG, log);}
    public static void e(int    log) {e(TAG, ""+log);}


    public static void v(String tag, String log) {
        log(Log.VERBOSE, tag, log);
    }
    public static void v(String tag, int log) {v(tag, "" + log);}
    public static void v(String tag, String log, boolean out){if (out)v(tag, log);}
    public static void v(String tag, int    log, boolean out){if (out)v(tag, log);}
    public static void v(String log, boolean out){if (out) v(log);}
    public static void v(int    log, boolean out){if (out) v(log);}
    public static void v(String log) {v(TAG, log);}
    public static void v(int    log) {v(TAG, ""+log);}


    public static void i(String tag, String log) {
        log(Log.INFO, tag, log);
    }
    public static void i(String tag, int log) {i(tag, "" + log);}
    public static void i(String tag, String log, boolean out){if (out)i(tag, log);}
    public static void i(String tag, int    log, boolean out){if (out)i(tag, log);}
    public static void i(String log, boolean out){if (out) i(log);}
    public static void i(int    log, boolean out){if (out) i(log);}
    public static void i(String log) {i(TAG, log);}
    public static void i(int    log) {i(TAG, ""+log);}


    private static void log(int level, String tag, String log) {
        if (bOutLog) {
            switch (level) {
                case Log.DEBUG:
                    Log.d(tag, log);
                    break;
                case Log.ERROR:
                    Log.e(tag, log);
                    break;
                case Log.INFO:
                    Log.i(tag, log);
                    break;
                case Log.VERBOSE:
                    Log.v(tag, log);
                    break;
                case Log.WARN:
                    Log.w(tag, log);
                    break;
                default:
                    Log.d(tag, log);
            }
        }
        if (bSaveLog) {
            String logInfo = log;
            try {
                StackTraceElement[] a = new Throwable().getStackTrace();
                StackTraceElement ste = a[0];
                for (StackTraceElement anA : a) {
                    if (!anA.getMethodName().equals("log") &&
                            !anA.getMethodName().equals("e") &&
                            !anA.getMethodName().equals("d") &&
                            !anA.getMethodName().equals("v") &&
                            !anA.getMethodName().equals("i")) {
                        ste = anA;
                        break;
                    }
                }
                String  sClassName = ste.getClassName();
                String sMethodName = ste.getMethodName();
                int          iLine = ste.getLineNumber();
                String   sFileName = ste.getFileName();

                String sTmpClassName = "";
                int iPos = sClassName.lastIndexOf(".");
                if(iPos <=0 ) {
                    sTmpClassName = sClassName;
                } else {
                    sTmpClassName = sClassName.substring(iPos+1);
                }

                SimpleDateFormat df = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss:SSS]");
                String        sTime = df.format(new Date());

                logInfo = sTime + "[" + sFileName + ":" + iLine + " " + sTmpClassName + "::" + sMethodName + "] " + log;
            } catch (Exception ex) {
                ex.printStackTrace();
                logInfo = log;
            }
            save0(logInfo+"\n");
        }
    }

    private static void save0(String log) {
        long timeStar = System.currentTimeMillis();
        try {
            File file = new File("/sdcard/demo.txt");
            //true，表示追加到文本
            FileOutputStream fos = new FileOutputStream(file, true);
            byte[] bytes = log.getBytes();
            fos.write(bytes);
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        long timeEnd = System.currentTimeMillis();
        System.out.println("Write time :" + (timeEnd - timeStar) + "ms");
    }

    private static void save1(String log) {
        long timeStar = System.currentTimeMillis();
        try {
            File file = new File("/sdcard/demo.txt");
            //true，表示追加到文本
            FileOutputStream fos = new FileOutputStream(file, true);
            FileInputStream fis = new FileInputStream(file);
            FileChannel fileChannel = fis.getChannel();

            MappedByteBuffer buffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, log.getBytes().length);
            buffer.put(log.getBytes());
            buffer.flip();

            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        long timeEnd = System.currentTimeMillis();
        System.out.println("Write time :" + (timeEnd - timeStar) + "ms");
    }

    private static void save2(String log) {
        long timeStar = System.currentTimeMillis();
        try {
            RandomAccessFile raf = new RandomAccessFile("/sdcard/demo.txt", "rw");
            MappedByteBuffer buffer = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, raf.length(), log.getBytes().length);
            buffer.put(log.getBytes());
            buffer.flip();
            raf.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        long timeEnd = System.currentTimeMillis();
        System.out.println("Write time :" + (timeEnd - timeStar) + "ms");
    }
}
